﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.SqlClient;
using System.Linq;
using System.Linq.Dynamic;
using System.Transactions;
using PagedList;
using Sovigaz.DataProvider;
using Utilities;

namespace Sovigaz.Permission.Repositories
{
    public class IndemnifyProductRepository : GenericRepository
    {
        public IndemnifyProductRepository()
            : base("IndemnifyProductID")
        {
        }

        public ICollection<IndemnifyProductComplex> IndemnifyProducts { get; set; }

        #region Get

        public IndemnifyProductRepository GetList(string whereClause, string orderBy, string orderDirection, int pageNumber)
        {
            var query = _context.IndemnifyProducts
                .Join(_context.Partners,i=>i.PartnerID,p=>p.PartnerID,(i,p)=> new IndemnifyProductComplex()
                {
                    IndemnifyProductID = i.IndemnifyProductID,
                    IndemnifyProductCode = i.IndemnifyProductCode,
                    PartnerID = i.PartnerID,
                    PartnerName=p.PartnerName,
                    NumberLost = _context.IndemnifyProductLines.Count(il => il.IndemnifyProductID == i.IndemnifyProductID && !il.IsIndemnify),
                    NumberIndemnify = _context.IndemnifyProductLines.Count(il => il.IndemnifyProductID == i.IndemnifyProductID && il.IsIndemnify),
                    Date = i.Date,
                    Reason=i.Reason,
                    Description = i.Description,
                    Status = i.Status,
                    IsDeleted=i.IsDeleted,
                    UpdatedName=_context.Users.FirstOrDefault(u=>u.UserID==i.UpdatedBy).FullName
                })
                .Where(whereClause)
                .OrderBy(String.Format("{0} {1}", orderBy.Trim(), orderDirection.Trim()))
                .ToPagedList(pageNumber, DefaultPageSize);

            TotalItemCount = query.TotalItemCount;
            TotalItemOnPage = query.Count;
            PageCount = query.PageCount;
            PageNumber = query.PageNumber;
            IndemnifyProducts = query.ToList();

            return this;
        }

        public IndemnifyProductRepository GetList(string whereClause, string orderBy, string orderDirection, int pageNumber, DateTime datefrom, DateTime dateto)
        {
            dateto.AddDays(1);
            var query = _context.IndemnifyProducts
                .Join(_context.Partners, i => i.PartnerID, p => p.PartnerID, (i, p) => new IndemnifyProductComplex()
                {
                    IndemnifyProductID = i.IndemnifyProductID,
                    IndemnifyProductCode = i.IndemnifyProductCode,
                    PartnerID = i.PartnerID,
                    PartnerName = p.PartnerName,
                    NumberLost = _context.IndemnifyProductLines.Count(il => il.IndemnifyProductID == i.IndemnifyProductID && !il.IsIndemnify),
                    NumberIndemnify = _context.IndemnifyProductLines.Count(il => il.IndemnifyProductID == i.IndemnifyProductID && il.IsIndemnify),
                    Date = i.Date,
                    Reason = i.Reason,
                    Description = i.Description,
                    Status = i.Status,
                    IsDeleted = i.IsDeleted,
                    UpdatedName = _context.Users.FirstOrDefault(u => u.UserID == i.UpdatedBy).FullName
                })
                .Where(whereClause)
                .Where(i => i.Date >= datefrom.Date && i.Date <= dateto.Date)
                .OrderBy(String.Format("{0} {1}", orderBy.Trim(), orderDirection.Trim()))
                .ToPagedList(pageNumber, DefaultPageSize);

            TotalItemCount = query.TotalItemCount;
            TotalItemOnPage = query.Count;
            PageCount = query.PageCount;
            PageNumber = query.PageNumber;
            IndemnifyProducts = query.ToList();

            return this;
        }

        public IndemnifyProduct GetByID(int id)
        {
            var item = _context.IndemnifyProducts.FirstOrDefault(i => i.IndemnifyProductID == id && !i.IsDeleted);
            if (item != null)
            {
                var repositoryline = new IndemnifyProductLineRepository();
                item.IndemnifyProductLines = repositoryline.GetByIndemnifyProductID(item.IndemnifyProductID);
            }
            else item = new IndemnifyProduct();
            return item;
        }

        #endregion

        #region Put

        public int Update(IndemnifyProduct item)
        {
            var update = new IndemnifyProduct();
            var indemnifyProductLineRepository = new IndemnifyProductLineRepository();
            update.IndemnifyProductCode = GenerateCode.GetCode(GetNextIndex(), CodeType.IdemnifyProduct);
            using (var scope = new TransactionScope())
            {
                if (item.IndemnifyProductID > 0)
                {
                    update = GetByID(item.IndemnifyProductID);                    
                    if (!Utility.ArrayEqual(update.Tstamp, item.Tstamp))
                        throw ExceptionHelper.CreateHttpResponseException("Dữ liệu đã bị cập nhật bởi người sử dụng khác.");
                }
                update.IndemnifyProductID = item.IndemnifyProductID;
                update.Date = item.Date;
                update.PartnerID = item.PartnerID;
                update.Reason = item.Reason;
                update.Description = item.Description;
                update.Status = item.Status;
                update.Status = item.Status;
                if (update.IndemnifyProductID == 0)
                    _context.IndemnifyProducts.Add(update);
                _context.SaveChanges();
                _context.Entry(update).Reload();
                indemnifyProductLineRepository.Update(item.IndemnifyProductLines as List<IndemnifyProductLine>, update);
                scope.Complete();
            }
            return update.IndemnifyProductID;
        }

        #endregion

        #region Delete

        public void Delete(int id)
        {
            var item = GetByID(id);
            var indemnifyProductLineRepository = new IndemnifyProductLineRepository();

            if (item != null)
            {
                if (item.Status == IndemnifyProductStatus.N.ToString())
                {
                    _context.IndemnifyProducts.Remove(item);
                    indemnifyProductLineRepository.DeleteByIndemnifyProduct(item);
                }
                _context.SaveChanges();
            }
        }

        public void Delete(string[] idArr)
        {
            foreach (var id in idArr) Delete(ConvertUtility.IntParse(id));
        }

        #endregion

        public int GetNextIndex()
        {
            if (_context.IndemnifyProducts.FirstOrDefault() == null) return 1;
            return _context.IndemnifyProducts.Max(i => i.IndemnifyProductID) + 1;
        }

        public void UpdateStatus(int id, string status)
        {
            var item = GetByID(id);
            if (item != null && item.Status!=status)
            {
                item.Status = status;
                var productRepository = new ProductRepository();
                if (item.Status == IndemnifyProductStatus.C.ToString()) 
                { 
                    var list= item.IndemnifyProductLines as List<IndemnifyProductLine>;
                    for (int i = 0; i < list.Count; i++)
                    {
                        var product=productRepository.GetByID(list[i].ProductID);
                        if (product != null)
                        {
                            if (!list[i].IsIndemnify)
                                product.Status = ProductStatus.M.ToString();
                            else
                            {
                                product.IsIndemnify = true;
                                product.OwnerID = 1;
                            }
                            productRepository.Update(product);
                        }
                    }
                }
            }
            _context.SaveChanges();
        }

        public void UpdateStatus(string[] ids, string status)
        {
            foreach (var id in ids)
                UpdateStatus(ConvertUtility.IntParse(id), status);
        }

        public bool canEdit(int id)
        {
            if (id == 0) return true;
            if (GetByID(id).Status == IndemnifyProductStatus.N.ToString()) return true;
            return false;
        }

    }

    public class IndemnifyProductLineRepository : GenericRepository
    {
        public IndemnifyProductLineRepository()
            : base("IndemnifyProductLineID")
        {
        }

        public ICollection<IndemnifyProductLine> IndemnifyProductLines { get; set; }

        public ICollection<IndemnifyProductLine> GetByIndemnifyProductID(int indemnifyProductID)
        {
            return _context.IndemnifyProductLines.Where(i => i.IndemnifyProductID == indemnifyProductID).ToList();
        }

        public void DeleteByIndemnifyProduct(IndemnifyProduct indemnifyProduct)
        {
            List<IndemnifyProductLine> list = GetByIndemnifyProductID(indemnifyProduct.IndemnifyProductID) as List<IndemnifyProductLine>;
            if (list != null)
            {
                for (int i = 0; i < list.Count; i++)
                    _context.IndemnifyProductLines.Remove(list[i]);
            }
            _context.SaveChanges();
        }

        public void Update(List<IndemnifyProductLine> IndemnifyProductLines, IndemnifyProduct indemnifyProduct)
        {
            if (IndemnifyProductLines != null)
            {
                this.DeleteByIndemnifyProduct(indemnifyProduct);
                for (int i = 0; i < IndemnifyProductLines.Count; i++)
                {
                    var item = new IndemnifyProductLine();
                    item.IndemnifyProductID = indemnifyProduct.IndemnifyProductID;
                    item.IsIndemnify = IndemnifyProductLines[i].IsIndemnify;
                    item.ProductID = IndemnifyProductLines[i].ProductID;
                    IndemnifyProductLines[i].IndemnifyProductID = indemnifyProduct.IndemnifyProductID;
                    _context.IndemnifyProductLines.Add(item);
                }
                _context.SaveChanges();
            }
        }
    }
}
